;
; RAWKEY.ASM  Raw Int-9 level keyboard handling
;
; (C) 12/9/88  M.R.Dobie, hacked by A.Key
;
;...sincludes:0:
		INCLUDE	INTDOS.INC
;...e
;...sdata_seg:0:
data_seg	SEGMENT 'data'

sccs_id		DB	'@(#)Raw Keyboard Reader  12/9/88', 0

key_translator	DB	0, 27, '1234567890-=', 8
		DB	9, 'QWERTYUIOP[]', 13
		DB	0, "ASDFGHJKL;'`"
		DB	0, '\ZXCVBNM,./', 0, 0
		DB	0, ' ', 0

n_keys		EQU	59		; numbered 0 to 58

data_seg	ENDS
;...e
;...sRAWKEY_TEXT:0:
RAWKEY_TEXT	SEGMENT PUBLIC 'code'

		ASSUME	CS:RAWKEY_TEXT,DS:RAWKEY_TEXT

;...spublics:0:
		PUBLIC	rk_init
		PUBLIC	rk_deinit
		PUBLIC	rk_wait_release
		PUBLIC	rk_wait_keyp
		PUBLIC	rk_get_joystick
;...e
;...svars:0:
int9st		DD	?		; old INT9 vector

keypress	DB	0FFH		; latest key pressed

joyvar		DB	0		; joystick status variable

; table of key numbers - values of joyvar

joytab		DB	47H,00001010B	; up left
		DB	48H,00001000B	; up
		DB	49H,00001001B	; up right
		DB	4BH,00000010B	; left
		DB	4DH,00000001B	; right
		DB	4FH,00000110B	; down left
		DB	50H,00000100B	; down
		DB	51H,00000101B	; down right
		DB	1CH,00010000B	; return
		DB	39H,00100000B	; space
		DB	4CH,00100000B	; middle key
		DB	01H,01000000B	; escape
		DB	52H,10000000B	; insert key
		DB	255
;...e

;...svoid pascal rk_init\40\\41\:0:
;
; Initialise the INT9 vector
;
rk_init		PROC	FAR

		PUSH	DS
		PUSH	ES
		PUSH	BX
		PUSH	DX

		MOV	AL,009H
		DOSCALL dos_get_ivec	; ES:BX = old INT9 handler

		MOV	WORD PTR CS:[int9st],ES
		MOV	WORD PTR CS:[int9st+2],BX
					; save old vector

		MOV	AX,SEG RAWKEY_TEXT
		MOV	DS,AX
		MOV	DX,OFFSET keyint
					; DS:DX = keyint (my handler)
		MOV	AL,009H
		DOSCALL	dos_set_ivec	; set vector

		POP	DX
		POP	BX
		POP	ES
		POP	DS
		RET

rk_init		ENDP
;...e
;...svoid pascal rk_deinit\40\\41\:0:
;
; Restore the old INT9 handler
;
rk_deinit	PROC	FAR

		PUSH	DS
		PUSH	DX

		MOV	DS,WORD PTR CS:[int9st]	; DS:DX = old vector
		MOV	DX,WORD PTR CS:[int9st+2]
		MOV	AL,009H
		DOSCALL	dos_set_ivec		; restore vector

		POP	DX
		POP	DS

		RET

rk_deinit	ENDP
;...e
;...svoid pascal rk_wait_release\40\\41\:0:
;
; Wait for all keys to be released
;
rk_wait_release	PROC	FAR

rk_waitloop:	CMP	CS:[joyvar],0
		JNE	rk_waitloop

		RET

rk_wait_release	ENDP
;...e
;...sint pascal rk_wait_keyp\40\\41\:0:
;
; int pascal rk_wait_keyp()
;
; Wait for any key to be pressed
;
rk_wait_keyp	PROC	FAR

		PUSH	BX

wk_1:		TEST	CS:[keypress],080H
					; if set => either 255 or last key
					; interrupt notified us of a release
		JZ	wk_1

wk_2:		TEST	CS:[keypress],080H
					; if reset => a key pressed message
					; has recently been sent us
		JNZ	wk_2
;
; Unfortunately, the key at this stage is a scan-code, not in ASCII
;
		MOV	AL,CS:[keypress]
		CMP	AL,n_keys
		JA	wk_1		; loop until allowable key

		PUSH	DS
		MOV	BX,SEG data_seg
		MOV	DS,BX
		MOV	BX,OFFSET key_translator
		XLAT
		POP	DS
		AND	AL,AL
		JZ	wk_1		; duff code, so ignore
		XOR	AH,AH

		POP	BX

		RET

rk_wait_keyp	ENDP
;...e
;...sint pascal rk_get_joystick\40\\41\:0:
;
; Return current "joystick" status
;
rk_get_joystick	PROC	FAR

		XOR	AH,AH
		MOV	AL,CS:[joyvar]
		RET

rk_get_joystick	ENDP
;...e

;...skeyint:0:
;
; Keyboard interrupt handler
;
keyint		PROC	NEAR

		STI			; disable interrupts
		PUSH	AX
		PUSH	DS
		MOV	AX,SEG RAWKEY_TEXT
		MOV	DS,AX

		IN	AL,060H		; get key pressed
		PUSH	AX		; save it
		IN	AL,061H
		MOV	AH,AL
		OR	AL,080H
		OUT	061H,AL
		XCHG	AL,AH
		OUT	061H,AL
		POP	AX		; retrieve key pressed
		CMP	AL,255
		JE	keyintret	; if key=255 then finish

		MOV	[keypress],AL	; store pressed key

		CALL	joyser		; call service routine for key

keyintret:	CLI			; finish
		MOV	AL,020H		; re-enable keyboard
		OUT	020H,AL
		POP	DS
		POP	AX
		IRET

keyint		ENDP
;...e
;...sjoyser:0:
;
; key service routine - performs joystick emulation
;
; IN
;	AL = key pressed

; OUT
;	joyvar is set up

; Format of joyvar (1 byte)
; 	ins esc space ret up down left right

joyser		PROC	NEAR

		PUSH	BX		; save registers
		PUSH	CX

		MOV	BX,OFFSET joytab

chk_key:	MOV	AH,[BX]		; get a key code
		MOV	CH,[BX+1]	; CH = or mask
		INC	BX
		INC	BX		; to next key
		CMP	AH,255		; end of table ?
		JE	joyret		; if end of table, finish

		CMP	AH,AL		; is this key pressed ?
		JNE	chk_release

		OR	[joyvar],CH	; set bits in status
		JMP	joyret		; finish

chk_release:	OR	AH,080H		; set top bit
		CMP	AH,AL		; is this key released ?
		JNE	chk_key		; if not, try next key

		NOT	CH		; complement it
		AND	[joyvar],CH	; reset status bits

joyret:		POP	CX
		POP	BX		; restore registers
		RET

joyser		ENDP
;...e

RAWKEY_TEXT	ENDS
;...e
END
